package com.sfdk.graphics.elements
{
    import com.sfdk.graphics.engine.animation.AnimatedBitmap;
    import com.sfdk.graphics.engine.api.IGraphicElement;
    import com.sfdk.pools.AnimatedBitmapPool;
    import com.sfdk.utils.IntPoint;

    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.geom.Point;

    public class GraphicElement extends EventDispatcher implements IGraphicElement
    {
        protected var _currentAction:String = "Marche";
        protected var _currentFace:String = "Face"

        protected var _currentAnimation:Array;
        protected var _currentAnimationIndex:int;
        protected var _currentAnimationLength:int;
        protected var _currentDuration:int;

        protected var _currentOffsetX:int;
        protected var _currentOffsetY:int;

        protected var _isOnScreen:Boolean;
        protected var _animatedBitmapType:String;
        protected var _animatedBitmap:AnimatedBitmap;
        protected var _isVisible:Boolean = true;
        protected var _isMovable:Boolean = false;
        protected var _hasMoved:Boolean = true;
        protected var _hasChanged:Boolean = false;
        protected var _currentTileID:int;

        public function GraphicElement(animatedBitmapType:String) {
            _animatedBitmapType = animatedBitmapType;
            initElement();
        }

        protected function initElement():void {
            _position = new Point();
            _animatedBitmap = AnimatedBitmapPool.getFromPool(_animatedBitmapType);
            if (!_animatedBitmap.isLoaded) {
                _animatedBitmap.addEventListener("animationLoaded", onAnimationLoaded);
            }
            else {
                onAnimationLoaded();
            }
        }

        private var _viewCache:BitmapData;

        public function get view():BitmapData {
            if (!_viewCache)
                _viewCache = _animatedBitmap.getView(_currentTileID);
            return _viewCache;
        }

        protected var _position:Point;

        public function get position():Point {
            _position.x = _x + _currentOffsetX;
            _position.y = _y + _currentOffsetY;
            return _position;
        }

        public function get tilePosition():Point {
            _position.x = _x;
            _position.y = _y;
            return _position;
        }

        private var _tilePosition:IntPoint = new IntPoint();

        public function get tileBasedPosition():IntPoint {
            _tilePosition.x = _x / 24;
            _tilePosition.y = _y / 24;
            return _tilePosition;
        }

        public function get isVisible():Boolean {
            return _isVisible;
        }


        public function set isVisible(value:Boolean):void {
            _isVisible = value;
        }

        protected var _x:Number = 0;

        public function set x(value:Number):void {
            _x = int(value * 1000) / 1000;
            _hasChanged = true;
        }

        public function get x():Number {
            return _x;
        }


        protected var _y:Number = 0;

        public final function get y():Number {
            return _y;
        }

        public final function set y(value:Number):void {
            _y = int(value * 1000) / 1000;
            _hasChanged = true;
        }

        protected var _id:int = 0;

        public function set id(value:int):void {
            _id = value;
        }

        public function get id():int {
            return _id;
        }

        public final function get hasChanged():Boolean {
            return _hasChanged;
        }

        public final function set hasChanged(value:Boolean):void {
            if (value)
                _viewCache = null;
            _hasChanged = value;
        }

        public final function get hasMoved():Boolean {
            if (!_animatedBitmap.isLoaded)
                return false;
            return _hasMoved;
        }

        public final function set hasMoved(value:Boolean):void {
            _hasMoved = value;
        }


        public final function get isOnScreen():Boolean {
            if (!_animatedBitmap.isLoaded)
                return false;
            return _isOnScreen;
        }

        public final function set isOnScreen(value:Boolean):void {
            _isOnScreen = value;
        }

        public function update(inMenu:Boolean):Boolean {
            if (!_animatedBitmap || !_animatedBitmap.isLoaded)
                return false;
            updateAnimation();
            return true;
        }

        protected function set currentFace(value:String):void {
            if (_currentFace != value) {
                _currentFace = value;
                _currentAnimation = _animatedBitmap.getAnimationData(_currentFace, _currentAction);
                _currentAnimationLength = _currentAnimation.length;
                _currentDuration = 0;
            }
        }

        protected function set currentAction(value:String):void {
            if (_currentAction != value) {
                _currentAction = value;
                _currentAnimation = _animatedBitmap.getAnimationData(_currentFace, _currentAction);
                _currentAnimationLength = _currentAnimation.length;
                _currentDuration = 0;
            }
        }

        protected function updateAnimation():void {
            if (_currentDuration == 0) {
                _currentAnimationIndex++;
                _currentAnimationIndex = _currentAnimationIndex % _currentAnimationLength;
                var currentAnimationInfo:Object = _currentAnimation[_currentAnimationIndex];
                _currentTileID = currentAnimationInfo.id;
                _currentDuration = currentAnimationInfo.duration
                if (_currentDuration == 0)
                    _currentDuration = -1;

                _currentOffsetX = currentAnimationInfo.xOffset;
                _currentOffsetY = currentAnimationInfo.yOffset;
                hasChanged = true;
            }
            else if (_currentDuration != -1) {
                _currentDuration--;
            }
            else if (_currentDuration == -1) {
                var currentAnimationIndex:int = _currentAnimationIndex % _currentAnimationLength;
                currentAnimationInfo = _currentAnimation[currentAnimationIndex];
                if (currentAnimationInfo.duration != -1)
                    _currentDuration = 0;
            }
        }

        protected function onAnimationLoaded(e:Event = null):void {
            _currentAnimation = _animatedBitmap.getAnimationData(_currentFace, _currentAction);
            _currentAnimationLength = _currentAnimation.length;
            hasChanged = true;
        }
    }
}